package org.example.atomictest;

import lombok.extern.slf4j.Slf4j;
import org.example.utils.Sleeper;

import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicStampedReference;

/**
 * @author zhengdp
 * @Description 原子引用 ABA问题
 * @Date 2022/11/20 18:59
 * @Created by zhengdp
 */
@Slf4j(topic = "c.AtomicReferenceABA")
public class AtomicReferenceABA {

    static AtomicStampedReference<String> ref = new AtomicStampedReference<>("A",0);

    public static void main(String[] args) {
        log.info("Main Start ...");

        String prev = ref.getReference();
        // 获取版本号
        int version = ref.getStamp();
        log.info("Stamp : {}",version);
        other();
        log.info("Stamp : {}",version);
        Sleeper.sleep(1000);
        log.info("change A -> C {}",ref.compareAndSet(prev,"C",version,version + 1));
    }

    static void other(){
        new Thread(() -> {
            int stamp = ref.getStamp();
            log.info("Stamp : {} ",stamp);
            log.info("change A -> B {}",ref.compareAndSet(ref.getReference(),"B", stamp,stamp + 1));
        },"t1").start();
        Sleeper.sleep(500);
        new Thread(() -> {
            int stamp = ref.getStamp();
            log.info("Stamp : {} ",stamp);
            log.info("change B -> A {}",ref.compareAndSet(ref.getReference(),"A",stamp,stamp + 1));
        },"t2").start();
    }
}
